[BALLOON] Replace alloc_empty_page_range with new helper alloc_empty_pages_and_pagevec.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 6 Oct 2006 10:52:41 +0000 (11:52 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 6 Oct 2006 10:52:41 +0000 (11:52 +0100)
This is a better fit with all the callers, who now allocate discontiguous empty pages.
Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c
linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c
linux-2.6-xen-sparse/include/xen/balloon.h

index ad3965566150ff1a6e53e2512621b9e231346b74..f4a7d4b39810fbe7bc04e381e0cfc3f71ee8f540 100644 (file)
@@ -534,87 +534,88 @@ static int dealloc_pte_fn(
        return 0;
 }
 
-struct page *balloon_alloc_empty_page_range(unsigned long nr_pages)
+struct page **alloc_empty_pages_and_pagevec(int nr_pages)
 {
-       unsigned long vstart, flags;
-       unsigned int  order = get_order(nr_pages * PAGE_SIZE);
-       int ret;
-       unsigned long i;
-       struct page *page;
+       unsigned long vaddr, flags;
+       struct page *page, **pagevec;
+       int i, ret;
 
-       vstart = __get_free_pages(GFP_KERNEL, order);
-       if (vstart == 0)
+       pagevec = kmalloc(sizeof(page) * nr_pages, GFP_KERNEL);
+       if (pagevec == NULL)
                return NULL;
 
-       scrub_pages(vstart, 1 << order);
-
-       balloon_lock(flags);
-       if (xen_feature(XENFEAT_auto_translated_physmap)) {
-               unsigned long gmfn = __pa(vstart) >> PAGE_SHIFT;
-               struct xen_memory_reservation reservation = {
-                       .nr_extents   = 1,
-                       .extent_order = order,
-                       .domid        = DOMID_SELF
-               };
-               set_xen_guest_handle(reservation.extent_start, &gmfn);
-               ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
-                                          &reservation);
-               if (ret == -ENOSYS)
-                       goto err;
-               BUG_ON(ret != 1);
-       } else {
-               ret = apply_to_page_range(&init_mm, vstart, PAGE_SIZE << order,
-                                         dealloc_pte_fn, NULL);
-               if (ret == -ENOSYS)
+       for (i = 0; i < nr_pages; i++) {
+               page = pagevec[i] = alloc_page(GFP_KERNEL);
+               if (page == NULL)
                        goto err;
-               BUG_ON(ret);
-       }
-       current_pages -= 1UL << order;
-       totalram_pages = current_pages;
-       balloon_unlock(flags);
 
-       schedule_work(&balloon_worker);
+               vaddr = (unsigned long)page_address(page);
 
-       flush_tlb_all();
+               scrub_pages(vaddr, 1);
 
-       page = virt_to_page(vstart);
+               balloon_lock(flags);
 
-       for (i = 0; i < (1UL << order); i++)
-               set_page_count(page + i, 1);
+               if (xen_feature(XENFEAT_auto_translated_physmap)) {
+                       unsigned long gmfn = page_to_pfn(page);
+                       struct xen_memory_reservation reservation = {
+                               .nr_extents   = 1,
+                               .extent_order = 0,
+                               .domid        = DOMID_SELF
+                       };
+                       set_xen_guest_handle(reservation.extent_start, &gmfn);
+                       ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+                                                  &reservation);
+                       if (ret == 1)
+                               ret = 0; /* success */
+               } else {
+                       ret = apply_to_page_range(&init_mm, vaddr, PAGE_SIZE,
+                                                 dealloc_pte_fn, NULL);
+               }
 
-       return page;
+               if (ret != 0) {
+                       balloon_unlock(flags);
+                       __free_page(page);
+                       goto err;
+               }
+
+               totalram_pages = --current_pages;
+
+               balloon_unlock(flags);
+       }
+
+ out:
+       schedule_work(&balloon_worker);
+       flush_tlb_all();
+       return pagevec;
 
  err:
-       free_pages(vstart, order);
+       balloon_lock(flags);
+       while (--i >= 0)
+               balloon_append(pagevec[i]);
        balloon_unlock(flags);
-       return NULL;
+       kfree(pagevec);
+       pagevec = NULL;
+       goto out;
 }
 
-void balloon_dealloc_empty_page_range(
-       struct page *page, unsigned long nr_pages)
+void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
 {
-       unsigned long i, flags;
-       unsigned int  order = get_order(nr_pages * PAGE_SIZE);
+       unsigned long flags;
+       int i;
+
+       if (pagevec == NULL)
+               return;
 
        balloon_lock(flags);
-       for (i = 0; i < (1UL << order); i++) {
-               BUG_ON(page_count(page + i) != 1);
-               balloon_append(page + i);
+       for (i = 0; i < nr_pages; i++) {
+               BUG_ON(page_count(pagevec[i]) != 1);
+               balloon_append(pagevec[i]);
        }
        balloon_unlock(flags);
 
-       schedule_work(&balloon_worker);
-}
+       kfree(pagevec);
 
-struct page *balloon_alloc_empty_page(void)
-{
-       return balloon_alloc_empty_page_range(1);
-}
-
-void balloon_free_empty_page(
-       struct page *page)
-{
-       balloon_dealloc_empty_page_range(page, 1);
+       schedule_work(&balloon_worker);
 }
 
 void balloon_release_driver_page(struct page *page)
@@ -630,10 +631,8 @@ void balloon_release_driver_page(struct page *page)
 }
 
 EXPORT_SYMBOL_GPL(balloon_update_driver_allowance);
-EXPORT_SYMBOL_GPL(balloon_alloc_empty_page_range);
-EXPORT_SYMBOL_GPL(balloon_dealloc_empty_page_range);
-EXPORT_SYMBOL_GPL(balloon_alloc_empty_page);
-EXPORT_SYMBOL_GPL(balloon_free_empty_page);
+EXPORT_SYMBOL_GPL(alloc_empty_pages_and_pagevec);
+EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec);
 EXPORT_SYMBOL_GPL(balloon_release_driver_page);
 
 MODULE_LICENSE("Dual BSD/GPL");
index 5d5856d8f90a844932df6b0eee4c44e0ed16c5d3..1941d61b0dfa7f3cb46b28344b25dbc679462801 100644 (file)
@@ -515,20 +515,13 @@ static int __init blkif_init(void)
                                        blkif_reqs, GFP_KERNEL);
        pending_grant_handles = kmalloc(sizeof(pending_grant_handles[0]) *
                                        mmap_pages, GFP_KERNEL);
-       pending_pages         = kmalloc(sizeof(pending_pages[0]) *
-                                       mmap_pages, GFP_KERNEL);
+       pending_pages         = alloc_empty_pages_and_pagevec(mmap_pages);
+
        if (!pending_reqs || !pending_grant_handles || !pending_pages)
                goto out_of_memory;
 
-       for (i = 0; i < mmap_pages; i++) {
-               pending_pages[i] = balloon_alloc_empty_page();
-               if (pending_pages[i] == NULL) {
-                       while (--i >= 0)
-                               balloon_free_empty_page(pending_pages[i]);
-                       goto out_of_memory;
-               }
+       for (i = 0; i < mmap_pages; i++)
                pending_grant_handles[i] = BLKBACK_INVALID_HANDLE;
-       }
 
        blkif_interface_init();
 
@@ -545,7 +538,7 @@ static int __init blkif_init(void)
  out_of_memory:
        kfree(pending_reqs);
        kfree(pending_grant_handles);
-       kfree(pending_pages);
+       free_empty_pages_and_pagevec(pending_pages, mmap_pages);
        printk("%s: out of memory\n", __FUNCTION__);
        return -ENOMEM;
 }
index 7f26492902952774c27788a079520adfd0f54da5..0a0d31fe2717b37406faf8df1f7d849485543e9d 100644 (file)
@@ -728,29 +728,17 @@ static void make_response(blkif_t *blkif, unsigned long id,
 static int req_increase(void)
 {
        int i, j;
-       struct page **pages = NULL;
 
        if (mmap_alloc >= MAX_PENDING_REQS || mmap_lock) 
                return -EINVAL;
 
-       pending_reqs[mmap_alloc] = kzalloc(sizeof(pending_req_t) *
-                                          blkif_reqs, GFP_KERNEL);
-       pages = kmalloc(sizeof(pages[0]) * mmap_pages, GFP_KERNEL);
+       pending_reqs[mmap_alloc]  = kzalloc(sizeof(pending_req_t)
+                                           * blkif_reqs, GFP_KERNEL);
+       foreign_pages[mmap_alloc] = alloc_empty_pages_and_pagevec(mmap_pages);
 
-       if (!pending_reqs[mmap_alloc] || !pages)
+       if (!pending_reqs[mmap_alloc] || !foreign_pages[mmap_alloc])
                goto out_of_memory;
 
-       for (i = 0; i < mmap_pages; i++) {
-               pages[i] = balloon_alloc_empty_page();
-               if (!pages[i]) {
-                       while (--i >= 0)
-                               balloon_free_empty_page(pages[i]);
-                       goto out_of_memory;
-               }
-       }
-
-       foreign_pages[mmap_alloc] = pages;
-
        DPRINTK("%s: reqs=%d, pages=%d\n",
                __FUNCTION__, blkif_reqs, mmap_pages);
 
@@ -768,7 +756,7 @@ static int req_increase(void)
        return 0;
 
  out_of_memory:
-       kfree(pages);
+       free_empty_pages_and_pagevec(foreign_pages[mmap_alloc], mmap_pages);
        kfree(pending_reqs[mmap_alloc]);
        WPRINTK("%s: out of memory\n", __FUNCTION__);
        return -ENOMEM;
@@ -776,15 +764,12 @@ static int req_increase(void)
 
 static void mmap_req_del(int mmap)
 {
-       int i;
-
        BUG_ON(!spin_is_locked(&pending_free_lock));
 
        kfree(pending_reqs[mmap]);
+       pending_reqs[mmap] = NULL;
 
-       for (i = 0; i < mmap_pages; i++)
-               balloon_free_empty_page(foreign_pages[mmap][i]);
-       kfree(foreign_pages[mmap]);
+       free_empty_pages_and_pagevec(foreign_pages[mmap_alloc], mmap_pages);
        foreign_pages[mmap] = NULL;
 
        mmap_lock = 0;
index 3cee68ffb44d7c2c31ed7335232fb665e98b996a..a75a4c9bc2f52e768e1ec7f76e02b2d12bc69af5 100644 (file)
@@ -1440,19 +1440,14 @@ static int __init netback_init(void)
        net_timer.data = 0;
        net_timer.function = net_alarm;
 
-       mmap_pages = kmalloc(sizeof(mmap_pages[0]) * MAX_PENDING_REQS,
-                            GFP_KERNEL);
-       if (mmap_pages == NULL)
-               goto out_of_memory;
+       mmap_pages = alloc_empty_pages_and_pagevec(MAX_PENDING_REQS);
+       if (mmap_pages == NULL) {
+               printk("%s: out of memory\n", __FUNCTION__);
+               return -ENOMEM;
+       }
 
        for (i = 0; i < MAX_PENDING_REQS; i++) {
-               page = mmap_pages[i] = balloon_alloc_empty_page();
-               if (page == NULL) {
-                       while (--i >= 0)
-                               balloon_free_empty_page(mmap_pages[i]);
-                       goto out_of_memory;
-               }
-               set_page_count(page, 1);
+               page = mmap_pages[i];
                SetPageForeign(page, netif_page_release);
                page->index = i;
        }
@@ -1478,11 +1473,6 @@ static int __init netback_init(void)
 #endif
 
        return 0;
-
- out_of_memory:
-       kfree(mmap_pages);
-       printk("%s: out of memory\n", __FUNCTION__);
-       return -ENOMEM;
 }
 
 module_init(netback_init);
index ce06f7ce58855753e9576f9f765c149d4d63f375..2614aa51269b91a1d0f42331a21a28af3100f7f7 100644 (file)
@@ -23,10 +23,9 @@ LIST_HEAD(tpmif_list);
 static tpmif_t *alloc_tpmif(domid_t domid, struct backend_info *bi)
 {
        tpmif_t *tpmif;
-       int i;
 
        tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL);
-       if (!tpmif)
+       if (tpmif == NULL)
                goto out_of_memory;
 
        memset(tpmif, 0, sizeof (*tpmif));
@@ -36,46 +35,27 @@ static tpmif_t *alloc_tpmif(domid_t domid, struct backend_info *bi)
        snprintf(tpmif->devname, sizeof(tpmif->devname), "tpmif%d", domid);
        atomic_set(&tpmif->refcnt, 1);
 
-       tpmif->mmap_pages = kmalloc(sizeof(tpmif->mmap_pages[0])
-                                   * TPMIF_TX_RING_SIZE, GFP_KERNEL);
+       tpmif->mmap_pages = alloc_empty_pages_and_pagevec(TPMIF_TX_RING_SIZE);
        if (tpmif->mmap_pages == NULL)
                goto out_of_memory;
 
-       for (i = 0; i < TPMIF_TX_RING_SIZE; i++) {
-               tpmif->mmap_pages[i] = balloon_alloc_empty_page();
-               if (tpmif->mmap_pages[i] == NULL) {
-                       while (--i >= 0)
-                               balloon_free_empty_page(tpmif->mmap_pages[i]);
-                       goto out_of_memory;
-               }
-       }
-
        list_add(&tpmif->tpmif_list, &tpmif_list);
        num_frontends++;
 
        return tpmif;
 
  out_of_memory:
-       if (tpmif != NULL) {
-               kfree(tpmif->mmap_pages);
+       if (tpmif != NULL)
                kmem_cache_free(tpmif_cachep, tpmif);
-       }
        printk("%s: out of memory\n", __FUNCTION__);
        return ERR_PTR(-ENOMEM);
 }
 
 static void free_tpmif(tpmif_t * tpmif)
 {
-       int i;
-
        num_frontends--;
-
        list_del(&tpmif->tpmif_list);
-
-       for (i = 0; i < TPMIF_TX_RING_SIZE; i++)
-               balloon_free_empty_page(tpmif->mmap_pages[i]);
-       kfree(tpmif->mmap_pages);
-
+       free_empty_pages_and_pagevec(tpmif->mmap_pages, TPMIF_TX_RING_SIZE);
        kmem_cache_free(tpmif_cachep, tpmif);
 }
 
index 4e27a2e39a76a826fc687a1bfacb0e03d3d94c72..d26c62bef4b5d1b5d4f6bb2ef1d05ef46b002460 100644 (file)
  */
 void balloon_update_driver_allowance(long delta);
 
-/* Allocate an empty low-memory page range. */
-struct page *balloon_alloc_empty_page_range(unsigned long nr_pages);
-
-/* Deallocate an empty page range, adding to the balloon. */
-void balloon_dealloc_empty_page_range(
-       struct page *page, unsigned long nr_pages);
-
-struct page *balloon_alloc_empty_page(void);
-void balloon_free_empty_page(struct page *page);
+/* Allocate/free a set of empty pages in low memory (i.e., no RAM mapped). */
+struct page **alloc_empty_pages_and_pagevec(int nr_pages);
+void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages);
 
 void balloon_release_driver_page(struct page *page);